package com.nus.frogworks;

import java.io.File;
import java.nio.ByteBuffer;
import java.util.Calendar;

import com.nus.frogworks.AccessoryEngine.IEngineCallback;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.SystemClock;
import android.view.Menu;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;

public class DriveCycleActivity extends Activity {
	
	private final int DEBUG_MODE = 0;
	private final int RIDE_MODE = 1;
	
	private final static String EXTRA_LOG = "com.nus.frogworks.LOG";
	private final static String EXTRA_BACKUP = "com.nus.frogworks.BACKUP";
	
	private boolean capacity_set = false;
	
	private int logFreq;
	private int backupFreq;
	
	private byte[] maxCapacityByteArray = {(byte)0x00,(byte)0x00,(byte)0x07,(byte)0xd0};
	
	private int MODE = DEBUG_MODE;
	//private int MODE = RIDE_MODE;
	
	private final double[] NEDA_URBAN = {0,0,0,0,0,0,0,0,0,0,0,0,3.744,7.488,11.232,
			14.976,14.976,14.976,14.976,14.976,14.976,14.976,14.976,14.976,12.492,
			10.008,6.66,3.312,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.988,5.976,
			8.964,11.952,14.94,14.94,14.94,18.324,21.708,25.092,28.476,31.86,31.86,
			31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,
			31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,29.124,
			26.388,23.652,20.916,18.18,15.444,12.708,9.972,9.972,9.972,6.624,3.276,
			0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.988,5.976,8.964,11.952,14.94,14.94
			,14.94,17.172,19.404,21.636,23.868,26.1,28.332,30.564,32.796,35.028,35.028,
			35.028,36.9,38.772,40.644,42.516,44.388,46.26,48.132,50.004,50.004,50.004,
			50.004,50.004,50.004,50.004,50.004,50.004,50.004,50.004,50.004,50.004,48.132,
			46.26,44.388,42.516,40.644,38.772,36.9,35.028,35.028,35.028,35.028,35.028,
			35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,
			31.896,28.764,25.632,22.5,19.368,16.236,13.104,9.972,9.972,6.624,3.276,0,0,0,
			0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.744,7.488,11.232,14.976,14.976,14.976,14.976,
			14.976,14.976,14.976,14.976,14.976,12.492,10.008,6.66,3.312,0,0,0,0,0,0,0,0,0,
			0,0,0,0,0,0,0,0,0,0,0,0,0,2.988,5.976,8.964,11.952,14.94,14.94,14.94,18.324,
			21.708,25.092,28.476,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,
			31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,
			31.86,31.86,31.86,29.124,26.388,23.652,20.916,18.18,15.444,12.708,9.972,9.972,
			9.972,6.624,3.276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.988,5.976,8.964,
			11.952,14.94,14.94,14.94,17.172,19.404,21.636,23.868,26.1,28.332,30.564,32.796,
			35.028,35.028,35.028,36.9,38.772,40.644,42.516,44.388,46.26,48.132,50.004,50.004,
			50.004,50.004,50.004,50.004,50.004,50.004,50.004,50.004,50.004,50.004,50.004,
			48.132,46.26,44.388,42.516,40.644,38.772,36.9,35.028,35.028,35.028,35.028,35.028,
			35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,
			31.896,28.764,25.632,22.5,19.368,16.236,13.104,9.972,9.972,6.624,3.276,0,0,0,0,
			0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.744,7.488,11.232,14.976,14.976,14.976,14.976,14.976,
			14.976,14.976,14.976,14.976,12.492,10.008,6.66,3.312,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
			0,0,0,0,0,0,0,0,2.988,5.976,8.964,11.952,14.94,14.94,14.94,18.324,21.708,25.092,
			28.476,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,
			31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,
			29.124,26.388,23.652,20.916,18.18,15.444,12.708,9.972,9.972,9.972,6.624,3.276,0,
			0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.988,5.976,8.964,11.952,14.94,14.94,14.94,
			17.172,19.404,21.636,23.868,26.1,28.332,30.564,32.796,35.028,35.028,35.028,36.9,
			38.772,40.644,42.516,44.388,46.26,48.132,50.004,50.004,50.004,50.004,50.004,50.004,
			50.004,50.004,50.004,50.004,50.004,50.004,50.004,48.132,46.26,44.388,42.516,40.644,
			38.772,36.9,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,
			35.028,35.028,35.028,35.028,35.028,35.028,31.896,28.764,25.632,22.5,19.368,16.236,
			13.104,9.972,9.972,6.624,3.276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.744,7.488,11.232,
			14.976,14.976,14.976,14.976,14.976,14.976,14.976,14.976,14.976,12.492,10.008,6.66,
			3.312,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.988,5.976,8.964,11.952,14.94,14.94,
			14.94,18.324,21.708,25.092,28.476,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,
			31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,31.86,
			31.86,31.86,31.86,29.124,26.388,23.652,20.916,18.18,15.444,12.708,9.972,9.972,9.972,
			6.624,3.276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.988,5.976,8.964,11.952,14.94,
			14.94,14.94,17.172,19.404,21.636,23.868,26.1,28.332,30.564,32.796,35.028,35.028,35.028,
			36.9,38.772,40.644,42.516,44.388,46.26,48.132,50.004,50.004,50.004,50.004,50.004,50.004,
			50.004,50.004,50.004,50.004,50.004,50.004,50.004,48.132,46.26,44.388,42.516,40.644,
			38.772,36.9,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,35.028,
			35.028,35.028,35.028,35.028,35.028,35.028,31.896,28.764,25.632,22.5,19.368,16.236,
			13.104,9.972,9.972,6.624,3.276,0,0,0,0,0,0};
	
	
	private final String LOG_FORMAT = "drivecycle-%d-%d-%d-%d-%d.csv";
	
	private String logName;
	
	private long startTime;
	
	TextView target, speed, voltage, current, battery, ambient, controller, motor, batteryLife;
	ProgressBar batteryBar;
	Handler mHandler = new Handler();
	
	private AccessoryEngine mEngine = null;
	private DataInputWrapper wrapper = null;
	
	File logFile;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		onNewIntent(getIntent());
		setContentView(R.layout.activity_drivecycle);

		speed = (TextView) findViewById(R.id.speed);
		voltage = (TextView) findViewById(R.id.voltage);
		current = (TextView) findViewById(R.id.current);
		battery = (TextView) findViewById(R.id.battery);
		ambient = (TextView) findViewById(R.id.ambient);
		controller = (TextView) findViewById(R.id.controller);
		motor = (TextView) findViewById(R.id.motor);
		target = (TextView) findViewById(R.id.target);
		batteryLife = (TextView) findViewById(R.id.battery_life);
		
		batteryBar = (ProgressBar) findViewById(R.id.battery_life_bar);
		batteryBar.setMax(wrapper.getMaxCapacity());
		startTime = SystemClock.elapsedRealtime();
		
		(new Thread(new Runnable()
        {

            @Override
            public void run()
            {
                while (!Thread.interrupted())
                    try
                    {	
                    	
                    	wrapper.writeEmptySignal();
                    	
                    	(new Thread((new Runnable(){
                    		@Override
                    		public void run(){
                    			try{
                    				wrapper.updateLogs();
                    			} catch (Exception e){
                    				L.d(e.getMessage());
                    			}
                    		}
                    	}))).start();
                    	    	
                		speed.post(new Runnable(){
                			@Override
                			public void run() {
                				speed.setText(wrapper.getSpeedString());
                			}	
                		});
                		voltage.post(new Runnable(){
                			@Override
                			public void run() {
                				voltage.setText(wrapper.getVoltageString());
                			}
                		});
                		current.post(new Runnable(){
                			@Override
                			public void run() {
                				current.setText(wrapper.getCurrentString());
                			}    			
                		});
                		battery.post(new Runnable(){
                			@Override
                			public void run() {
                				battery.setText(wrapper.getBatteryString());
                			}
                		});
                		motor.post(new Runnable(){
                			@Override
                			public void run() {
                				motor.setText(wrapper.getMotorString());
                			}
                		});
                		controller.post(new Runnable(){
                			@Override
                			public void run() {
                				controller.setText(wrapper.getControllerString());
                			}	
                		});
                		ambient.post(new Runnable(){
                			@Override
                			public void run() {
                				ambient.setText(wrapper.getAmbientString());
                			}
                		});
                		target.post(new Runnable(){
                			@Override
                			public void run(){
                				int second = (int) ((SystemClock.elapsedRealtime()-startTime)/1000);
                				if (second >= NEDA_URBAN.length){
                					second = NEDA_URBAN.length - 1;
                				}
                				target.setText(String.valueOf(NEDA_URBAN[second]));
                			}
                		});
                		batteryLife.post(new Runnable(){
                			@Override
                			public void run(){
                				batteryLife.setText(wrapper.getCapacityString());
                			}
                		});
                		mHandler.post(new Runnable(){
                			@Override
                			public void run(){
                				batteryBar.setProgress(wrapper.getBattCapacity());
                			}
                		});
                    }
                    catch (Exception e)
                    {
                    	L.d(e.getMessage());
                    }
            }
        })).start();
		
		//stop.setOnClickListener(this);

	}
	
	public boolean isExternalStorageWritable(){
		String state = Environment.getExternalStorageState();
		if(Environment.MEDIA_MOUNTED.equals(state)){
			return true;
		}
		return false;
	}
	
	public void stop_ride(View view){
		
		ByteBuffer capBuffer = ByteBuffer.allocate(4);
		capBuffer.putInt(wrapper.getBattCapacity());
		wrapper.write(capBuffer.array());
		
		Intent intent = new Intent(this,MainActivity.class);
		startActivity(intent);
	}

	
	@Override
	protected void onNewIntent(Intent intent) {
		logFreq = intent.getIntExtra(EXTRA_LOG, 100);
		backupFreq = intent.getIntExtra(EXTRA_BACKUP, 5);
		
		
		L.d("handling intent action: " + intent.getAction());
		if (mEngine == null) {
			mEngine = new AccessoryEngine(getApplicationContext(), mCallback);
		}
		
		Calendar currentTime = Calendar.getInstance();
		int currentMinute = currentTime.get(Calendar.MINUTE);
		int currentHour = currentTime.get(Calendar.HOUR_OF_DAY);
		int currentDay = currentTime.get(Calendar.DAY_OF_MONTH);
		int currentMonth = currentTime.get(Calendar.MONTH);
		int currentYear = currentTime.get(Calendar.YEAR);
		logName = String.format(LOG_FORMAT, currentMinute, currentHour,
				currentDay, currentMonth, currentYear);
		
		if(MODE==RIDE_MODE){
			if(isExternalStorageWritable()){
				wrapper = new PiWrapper(mEngine,logName);
			} else {
				wrapper = new PiWrapper(mEngine);
			}
			mEngine.onNewIntent(intent);
			super.onNewIntent(intent);
		} else if (MODE==DEBUG_MODE) {
			if(isExternalStorageWritable()){
				L.d("Gonna log");
				wrapper = new HistoricalDataWrapper(logName);
			} else {
				L.d("Not gonna log");
				wrapper = new HistoricalDataWrapper();
			}
			super.onNewIntent(intent);
			capacity_set = true;
			wrapper.updateInitialCapacity(maxCapacityByteArray);
		}
		wrapper.setLogFrequency(logFreq);
		wrapper.setBackupFrequency(backupFreq);
	}

	@Override
	protected void onDestroy() {
		mEngine.onDestroy();
		mEngine = null;
		wrapper = null;
		super.onDestroy();
	}

	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	private final IEngineCallback mCallback = new IEngineCallback() {
		@Override
		public void onDeviceDisconnected() {
			L.d("device physically disconnected");
		}

		@Override
		public void onConnectionEstablished() {
			L.d("device connected! ready to go!");
		}

		@Override
		public void onConnectionClosed() {
			L.d("connection closed");
		}

		@Override
		public void onDataRecieved(byte[] data, int num) {
			if(!capacity_set){
				wrapper.updateInitialCapacity(data);
			}
			wrapper.updateData(data);
		}
	};
	
}
